package com.batyuta.sort;


import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;
import org.apache.log4j.Logger;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.CountDownLatch;

/**
 *
 */
public class MergeThreadDivision extends AbstractMergeThread<MergeQueueItem> implements Runnable {
    private static Logger logger = Logger.getLogger(MergeThreadDivision.class);
    private Integer dept;
    private Integer lineCount;

    public MergeThreadDivision(Queue<MergeQueueItem> queueIn, Queue<MergeQueueItem> queueOut, CountDownLatch startSignal, CountDownLatch doneSignal) {
        super(queueIn, queueOut, startSignal, doneSignal);
    }

    @Override
    public MergeQueueItem process() {
        MergeQueueItem result;
        getLogger().info(this.getClass().getName() + "(" + getId() + "): start");
        while (null != (result = poll())) {
            getLogger().info(this.getClass().getName() + "(" + getId() + "): " + result.toString());
            dept = result.getDept();
            lineCount = result.getLineCount();
            divisionFile(result.getFileFirst());
        }
        return result;
    }
    // TODO: I don't know how to separate this process to different threads
    public File divisionFile(File inputFile) {

        String dirName = inputFile.getParent() + "/" + dept;
        File directory = new File(dirName);
        LineIterator lineIterator = null;
        try {
            FileUtils.deleteDirectory(directory);
            lineIterator = FileUtils.lineIterator(inputFile);
            List<String> inputData = new ArrayList<String>();
            int i = 0;
            while (lineIterator.hasNext()) {
                String myString = formatData(lineIterator.nextLine());
                File outputFile = new File(dirName + "/" + i++);
                addToResult(myString, inputData, outputFile, lineCount);
            }
            if (!inputData.isEmpty()) {
                write(inputData, new File(dirName + "/" + i));
            }
        } catch (IOException e) {
            getLogger().error(e, e);
        } finally {
            LineIterator.closeQuietly(lineIterator);
        }
        return directory;
    }

    public void addToResult(String item, List<String> result, File outputFile, Integer lineCount) throws IOException {
        result.add(item);
        addToResult(result, outputFile, lineCount);
    }

    private void addToResult(List<String> result, File outputFile, Integer lineCount) throws IOException {
        if (result.size() == lineCount) {
            write(result, outputFile);
        }
    }

    private void write(List<String> result, File outputFile) throws IOException {
        FileUtils.writeLines(outputFile, result);
        result.clear();
        addToQueue(outputFile);
    }

    private void addToQueue(File file) {
        add(new MergeQueueItem(file, null, lineCount, dept + 1));
    }

    @Override
    Logger getLogger() {
        return logger;
    }

    public static String formatData(String data) {
        String neLn;
        String[] spLn;
        if (null != data && (neLn = data.trim().toLowerCase()).length() > 0 && (spLn = neLn.split(" ")).length > 0) {
            data = spLn[0];
        } else {
            data = "";
        }
        return data;
    }
}
